package com.btr.uimeter.util;

import java.awt.Component;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;

/*****************************************************************************
 *  Builds a path for a component as condensed traversal path from the
 *  UI root frame to the given component.
 *   
 * @author Bernd Rosstauscher (java@rosstauscher.de) Copyright 2010
 ****************************************************************************/

public class UIComponentPathBuilder {
	
	/*************************************************************************
	 * Constructor
	 ************************************************************************/
	
	public UIComponentPathBuilder() {
		super();
	}
	
	/*************************************************************************
	 * Gets the compact component path as iterator that will deliver for all parts
	 * in the an identifier string. 
	 * @param c to get the path for.
	 * @return the iterator for the path.
	 ************************************************************************/
	
	public Iterator<String> getComponentPath(Component c) {
		LinkedList<String> pathSections = new LinkedList<String>();
		appendPath(c, pathSections);
		return pathSections.descendingIterator();
	}
	
	/*************************************************************************
	 * Gets the compact component path as a / separated string.
	 * @param c to get the path for.
	 * @return the path.
	 ************************************************************************/
	
	public String getComponentPathAsString(Component c) {
		Iterator<String> pathIterator = getComponentPath(c);
		StringBuilder sb = new StringBuilder();
		while (pathIterator.hasNext()) {
			String part = pathIterator.next();
			String cleanPathSegment = part.replace('/', '-').replace(' ', '-');
			sb.append("/").append(cleanPathSegment);
		}
		return sb.toString();
	}
	
	/*************************************************************************
	 * Method to append the "ID" of the given component to a UI hirarchy path.
	 * and recursively adds all IDs of the parent components.
	 * @param c
	 * @param pathSections
	 ************************************************************************/
	
	private void appendPath(Component c, List<String> pathSections) {
		if (c == null) {
			return;
		}
		if (c.getParent() instanceof JSplitPane) {
			c = buildIDForSplitPaneParent(c, pathSections);
		}
		if (c instanceof JTabbedPane) {
			buildIDForTab((JTabbedPane)c, pathSections);
		} else 
		if (c instanceof JFrame) {
			buildIDForFrame((JFrame) c, pathSections);
		} else
		if (c instanceof JInternalFrame) {
			buildIDForInternalFrame((JInternalFrame) c, pathSections);
		} else
		if (c instanceof JDialog) {
			buildIDForDialog((JDialog) c, pathSections);
		}
		appendPath(c.getParent(), pathSections);
	}

	/*************************************************************************
	 * @param c
	 * @param pathSections
	 ************************************************************************/
	
	private void buildIDForDialog(JDialog dialog, List<String> pathSections) {
		pathSections.add("dialog["+dialog.getTitle()+"]");
	}

	/*************************************************************************
	 * @param c
	 * @param path
	 ************************************************************************/
	
	private void buildIDForFrame(JFrame frame, List<String> pathSections) {
		pathSections.add("window["+frame.getTitle()+"]");
	}

	/*************************************************************************
	 * @param c
	 * @param pathSections
	 ************************************************************************/
	
	private void buildIDForInternalFrame(JInternalFrame frame, List<String> pathSections) {
		pathSections.add("frame["+frame.getTitle()+"]");
	}

	/*************************************************************************
	 * @param c
	 * @param path
	 * @return 
	 ************************************************************************/
	
	private JSplitPane buildIDForSplitPaneParent(Component c, List<String> pathSections) {
		JSplitPane split = ((JSplitPane)c.getParent());
		String side = (c == split.getLeftComponent()) ? "left" : "right";
		pathSections.add("split["+side+"]");
		return split;
	}

	/*************************************************************************
	 * @param tab
	 * @param pathSections
	 ************************************************************************/
	
	private void buildIDForTab(JTabbedPane tab, List<String> pathSections) {
		String titleAt = tab.getTitleAt(tab.getSelectedIndex());
		pathSections.add("tab["+titleAt+"]");
	}
	
}

